package particle.media;

import java.lang.ref.WeakReference;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Surface;

public class Player {
	static {
		// System.loadLibrary("Particle");
		// System.loadLibrary("ParticleOmxil");
		// System.loadLibrary("ParticleOmxal");
		// System.loadLibrary("ParticleIconv");
		// System.loadLibrary("ParticleMediaListener");
		System.loadLibrary("ParticleMediaClient");
		// System.loadLibrary("ParticleMedia");
		nativeInit();
	}
	private final static String TAG = "ParticleMedia";

	private int mNativeContext; // accessed by native methods
	private Surface mSurface; // accessed by native methods
	private EventHandler mEventHandler;

	public Player() {

		Looper looper;
		if ((looper = Looper.myLooper()) != null) {
			mEventHandler = new EventHandler(this, looper);
		} else if ((looper = Looper.getMainLooper()) != null) {
			mEventHandler = new EventHandler(this, looper);
		} else {
			mEventHandler = null;
		}

		nativeSetup(new WeakReference<Player>(this));
	}

	public static Player create(String uri) throws IllegalStateException {
		Player p = new Player();
		if (!p.nativeSetSource(uri)) {
			throw new IllegalStateException("can't open ");
		}
		return p;
	}

	public void setSource(String uri) throws IllegalStateException {
		if (!nativeSetSource(uri)) {
			throw new IllegalStateException("can't open ");
		}
	}

	public void pause() throws IllegalStateException {
		if (!nativePause()) {
			throw new IllegalStateException("can't pause 222");
		}
	}

	public boolean isPlaying() {
		return nativeIsPlaying();
	}

	public void prepare() throws IllegalStateException {
		boolean success2 = nativePrepare();
		if (!success2) {
			throw new IllegalStateException("can't prepare");
		}
	}

	public void start() throws IllegalStateException {
		if (!nativeStart()) {
			throw new IllegalStateException("can't start");
		}
	}

	public void stop() throws IllegalStateException {
		Log.i(TAG, "mediaplayer stop");
		if (!nativeStop()) {
			Log.i(TAG, "mediaplayer can't stop");
			throw new IllegalStateException("can't stop");
		}

		Log.i(TAG, "mediaplayer stop events");
	}

	public int seekTo(int msec) throws IllegalStateException {
		int position;

		position = nativeSeekTo(msec);
		if (position < 0) {
			throw new IllegalStateException("can't seek");
		}

		return position;
	}

	public int getCurrentPosition() throws IllegalStateException {
		int position;

		position = nativeGetCurrentPosition();
		if (position < 0) {
			throw new IllegalStateException("can't get current position");
		}

		return position;
	}

	public int getDuration() throws IllegalStateException {
		int duration;

		duration = nativeGetDuration();
		if (duration < 0) {
			throw new IllegalStateException("can't get duration");
		}
		return duration;
	}

	@Override
	protected void finalize() {
		nativeFinalize();
	}

	private static native final void nativeInit();

	private native boolean nativeSetSource(String path);

	private native final void nativeSetup(Object player_this);

	private native final void nativeFinalize();

	private native boolean nativePrepare();

	private native boolean nativeStart();

	private native boolean nativeStop();

	private native boolean nativePause();

	private native boolean nativeIsPlaying();

	private native int nativeSeekTo(int msec);

	private native int nativeGetCurrentPosition();

	private native int nativeGetDuration();

	public native boolean enableSpectrum(boolean enable);

	public native boolean getSpectrumData(int[] data);

	public native boolean enableAudioEq(boolean enable);

	public native boolean setEqualizerBandLevel(int bandIndex, int level);

	public native boolean isSpdifCablePlugIn();

	public native boolean enableSpdifOut(boolean enable);

	public native boolean isSpdifOut();

	public native boolean getAudioInfo(int[] info);

	public native boolean setOutMinSampleRate(int sampleRate);

	public native boolean setNextSongForGapless(String path);

	public native boolean gaplessPlay(String path);

	public native boolean setGaplessDuration(int msec);

	private static final int MEDIA_PLAYER_NOP = 0;
	private static final int MEDIA_PLAYER_ERROR = 1;
	private static final int MEDIA_PLAYER_COMPLETE = 2;

	private class EventHandler extends Handler {
		private Player mPlayer;

		public EventHandler(Player player, Looper looper) {
			super(looper);
			mPlayer = player;
		}

		@Override
		public void handleMessage(Message msg) {
			Log.i(TAG, "handleMessage msg");

			if (mPlayer.mNativeContext == 0) {
				Log.w(TAG, "mediaplayer went away with unhandled events");
				return;
			}

			switch (msg.what) {
			case MEDIA_PLAYER_COMPLETE:
				if (mOnCompletionListener != null)
					mOnCompletionListener.onCompletion(mPlayer);
				return;

			case MEDIA_PLAYER_ERROR:
				boolean error_was_handled = false;
				if (mOnErrorListener != null) {
					error_was_handled = mOnErrorListener.onError(mPlayer,
							msg.arg1, msg.arg2);
				}

				if (mOnCompletionListener != null && !error_was_handled) {
					mOnCompletionListener.onCompletion(mPlayer);
				}
				return;

			case MEDIA_PLAYER_NOP:
				break;

			default:
				Log.e(TAG, "Unknown message type " + msg.what);
				return;
			}
		}
	}

	private static void postEventFromNative(Object player_ref, int what,
			int arg1, int arg2, Object obj) {
		Log.i(TAG, "postEventFromNative " + what);

		Player p = (Player) ((WeakReference) player_ref).get();
		if (p == null) {
			return;
		}

		if (p.mEventHandler != null) {
			Message m = p.mEventHandler.obtainMessage(what, arg1, arg2, obj);
			p.mEventHandler.sendMessage(m);
		}
	}

	public interface OnCompletionListener {
		void onCompletion(Player p);
	}

	public void setOnCompletionListener(OnCompletionListener listener) {
		mOnCompletionListener = listener;
	}

	private OnCompletionListener mOnCompletionListener;

	public interface OnErrorListener {
		boolean onError(Player p, int what, int extra);
	}

	public void setOnErrorListener(OnErrorListener listener) {
		mOnErrorListener = listener;
	}

	private OnErrorListener mOnErrorListener;

}
